package com.iwat.hellospringcache.demos.web.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.framework.ProxyFactory;

import java.lang.reflect.Method;

/**
 * @author 王伟强
 */
public class SimpleAopExample {

    public static void main(String[] args) {
        // 创建目标对象
        MyService target = new MyService();

        // 创建通知对象 (MethodBeforeAdvice)
        MethodInterceptor advice = new MyBeforeAdvice();

        // 创建 Advisor，将通知对象包装成 Advisor
        MyAdvisor advisor = new MyAdvisor(advice);

        // 创建代理工厂
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setTarget(target);
        proxyFactory.addAdvisor(advisor);

        // 获取代理对象
        MyService proxy = (MyService) proxyFactory.getProxy();

        // 调用代理对象的方法 并增强
        proxy.doSomething();
        // 调用代理对象的方法 并增强
        proxy.doSomethingElse();
        // 调用代理对象的方法 但不增强
        proxy.notDoSomething();
    }

    static class MyService {
        void doSomething() {
            System.out.println("Original method: Doing something");
        }

        void doSomethingElse() {
            System.out.println("Original method: Doing something else");
        }

        void notDoSomething() {
            System.out.println("Original method: Not doing something");
        }
    }

    static class MyBeforeAdvice implements MethodInterceptor {
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            invocation.proceed();
            System.out.println("Before method execution: " + invocation.getMethod().getName());
            return null;
        }
    }

    static class MyAdvisor extends org.springframework.aop.support.DefaultPointcutAdvisor {
        public MyAdvisor(MethodInterceptor advice) {
            super(new MyPointcut(), advice);
        }
    }

    static class MyPointcut extends org.springframework.aop.support.StaticMethodMatcherPointcut {
        @Override
        public boolean matches(Method method, Class<?> targetClass) {
            // 切点条件，可以根据需要自定义匹配条件
            return method.getName().startsWith("do");
        }
    }
}
